package com.heima.wemedia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.MQConstants;
import com.heima.common.dtos.AppHttpCodeEnum;
import com.heima.common.dtos.PageResponseResult;
import com.heima.common.dtos.ResponseResult;
import com.heima.common.exception.LeadNewsException;
import com.heima.model.wemedia.dtos.WmNewsDownUpDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.BeanHelper;
import com.heima.utils.common.JsonUtils;
import com.heima.utils.common.ThreadLocalUtils;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import com.heima.wemedia.service.WmNewsService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @Autowired(required = false)
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired(required = false)
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private WmNewsAutoScanService wmNewsAutoScanService;

    @Override
    public PageResponseResult findList(WmNewsPageReqDto dto) {
        //参数校验
        dto.checkParam();

        //获取登录用户信息
        WmUser wmUser = (WmUser) ThreadLocalUtils.get();
        if (wmUser == null) {
            throw new LeadNewsException(AppHttpCodeEnum.NEED_LOGIN);
        }

        //封装条件
        IPage<WmNews> iPage = new Page<>(dto.getPage(), dto.getSize());

        //执行条件查询
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        //用户ID
        queryWrapper.eq("user_id", wmUser.getId());
        //状态
        if (dto.getStatus() != null) {
            queryWrapper.eq("status", dto.getStatus());
        }
        //关键字
        if (StringUtils.isNotEmpty(dto.getKeyword())) {
            queryWrapper.like("title", dto.getKeyword());
        }
        //频道
        if (dto.getChannelId() != null) {
            queryWrapper.eq("channel_id", dto.getChannelId());
        }
        if (dto.getBeginPubDate() != null && dto.getEndPubDate() != null) {
            queryWrapper.between("publish_time", dto.getBeginPubDate(), dto.getEndPubDate());
        }

        //排序创建时间倒序显示
        queryWrapper.orderByDesc("created_time");

        //封装结果返回
        iPage = page(iPage, queryWrapper);

        PageResponseResult pageResponseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) iPage.getTotal());
        pageResponseResult.setData(iPage.getRecords());
        pageResponseResult.setCode(AppHttpCodeEnum.SUCCESS.getCode());
        pageResponseResult.setErrorMessage(AppHttpCodeEnum.SUCCESS.getErrorMessage());

        return pageResponseResult;
    }

    @Override
    public ResponseResult submit(WmNewsDto dto) {
        //拷贝参数到WmNews对象中
        WmNews wmNews = BeanHelper.copyProperties(dto, WmNews.class);

        //文章作者
        WmUser wmUser = (WmUser) ThreadLocalUtils.get();
        if (wmUser == null) {
            throw new LeadNewsException(AppHttpCodeEnum.NEED_LOGIN);
        }
        wmNews.setUserId(wmUser.getId());

        //处理正常封面  stream流式编程
        if (CollectionUtils.isNotEmpty(dto.getImages())) {
            /**
             * stream(): 将List集合转换为stream流
             * map(): 对集合中的每个元素进行处理
             * collect(): 将集合中的每个处理后的结果进行聚合归总
             *    List collect(Collectors.toList()) 聚合成新的List集合
             *    Set collect(Collectors.toSet()) 聚合成新的Set集合
             *    Map collect(Collectors.toMap(xxx,xxx)) 聚合成新的Map集合
             *    String collect(Collectors.joinging(分隔符)) 使用指定的分隔符聚合成新的字符串
             */
            String coverStr = dto.getImages().stream().collect(Collectors.joining(","));
            wmNews.setImages(coverStr);
        }

        //需求1：处理自动封面
        /**
         * 从文章内容统计图片数量
         *     数量=0,为无图
         *     数量为1-2，为单图
         *     数量>=3,为三图
         */
        //从文章内容取出所有图片
        List<String> contentImages = getImagesFromContent(dto.getContent());
        if (dto.getType().equals((short) -1)) {
            int size = contentImages.size();
            if (size == 0) {
                //无图
                wmNews.setImages(null);
                wmNews.setType((short) 0);
            }
            if (size >= 1 && size <= 2) {
                //单图
                wmNews.setImages(contentImages.get(0));
                wmNews.setType((short) 1);
            }
            if (size >= 3) {
                //三图
                String imageStr = contentImages.subList(0, 3).stream().collect(Collectors.joining(","));
                wmNews.setImages(imageStr);
                wmNews.setType((short) 3);
            }
        }

        //需求2：新增或修改
        if (dto.getId() == null) {
            wmNews.setCreatedTime(new Date());
            save(wmNews);
        } else {
            updateById(wmNews);

            //删除文章和素材关系
            QueryWrapper<WmNewsMaterial> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("news_id", dto.getId());
            wmNewsMaterialMapper.delete(queryWrapper);
        }

        //需求3：绑定文章和素材关系
        //1）处理内容图片素材和文章的关系
        if (CollectionUtils.isNotEmpty(contentImages)) {
            List<Integer> materialIds = getMaterialIdFromUrl(contentImages);
            wmNewsMaterialMapper.saveNewsMaterial(materialIds, wmNews.getId(), 0);
        }

        //2）处理封面图片素材和文章的关系
        String images = wmNews.getImages();
        if (StringUtils.isNotEmpty(images)) {
            List<String> list = Arrays.asList(images.split(","));
            List<Integer> materialIds = getMaterialIdFromUrl(list);
            wmNewsMaterialMapper.saveNewsMaterial(materialIds, wmNews.getId(), 1);
        }

        //判断提交审核时自动调用该方法
        if (dto.getStatus().equals(WmNews.Status.SUBMIT.getCode())) {
            wmNewsAutoScanService.autoScanWmNews(wmNews.getId());
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 文章上下架
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDownUpDto dto) {
        //查询文章是否存在
        WmNews wmNews = getById(dto.getId());
        if (wmNews == null) {
            throw new LeadNewsException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //查询文章是否已经发布
        if (!wmNews.getStatus().equals(WmNews.Status.PUBLISHED.getCode())) {
            throw new LeadNewsException(400, "该文章未发布，请先发布");
        }

        //修改enable状态值
        wmNews.setEnable(dto.getEnable());
        updateById(wmNews);

        //发送消息给MQ，通知article服务更新状态
        Map msg = new HashMap();
        msg.put("articleId", wmNews.getArticleId());
        msg.put("enable", dto.getEnable());

        kafkaTemplate.send(MQConstants.WM_NEWS_UP_OR_DOWN_TOPIC, JsonUtils.toString(msg));

        //同步ES，进行上下架操作
        if (dto.getEnable().equals((short) 1)) {
            //上架
            kafkaTemplate.send(MQConstants.WM_NEW_UP_ES_TOPIC, wmNews.getArticleId().toString());
        } else {
            //下架
            kafkaTemplate.send(MQConstants.WM_NEW_DOWN_ES_TOPIC, wmNews.getArticleId().toString());
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 将url路径转换为素材ID
     *
     * @param contentImages
     * @return
     */
    private List<Integer> getMaterialIdFromUrl(List<String> contentImages) {
        QueryWrapper<WmMaterial> queryWrapper = new QueryWrapper();
        queryWrapper.in("url", contentImages).select("id");
        List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(queryWrapper);
        return wmMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());
    }

    /**
     * 从文章内容取出所有图片路径
     *
     * @param content
     * @return
     */
    private List<String> getImagesFromContent(String content) {
        List<String> contentImages = new ArrayList<>();
        if (StringUtils.isNotEmpty(content)) {
            List<Map> list = JsonUtils.toList(content, Map.class);
            for (Map map : list) {
                if (map.get("type").equals("image")) {
                    contentImages.add((String) map.get("value"));
                }
            }
        }
        return contentImages;
    }
}

